// -*- C++ -*-
/****************************************************************************
 *
 *  class TSurfaceNet
 *
 ****************************************************************************
 *
 *  File         :  TSurfaceNet.cc
 *
 *  Purpose      : 
 *
 ****************************************************************************
 *                 
 *  started      :  3  Jan 95    Robert Schweikert
 *  last change  :  20 Jan 95
 *
 ****************************************************************************/

#include "TSurfaceNet.h"

// This defines the three tables that are used to construct a
// surface net from a 3D binary (voxel) data set in TNetExtractor.cc
// This is derived from the two files  made with mathematica.

const int tr_direct[6][8] = {{1,-1,3,-1,5,-1,7,-1}, {-1,0,-1,2,-1,4,-1,6}, {2,3,-1,-1,6,7,-1,-1},
                 {-1,-1,0,1,-1,-1,4,5}, {4,5,6,7,-1,-1,-1,-1}, {-1,-1,-1,-1,0,1,2,3}};

const TNetExtractor::t1entry pt1[256] = {
{0,    1,    {0}},
{1,    1,    {1}},
{2,    1,    {2}},
{3,    1,    {3}},
{4,    1,    {4}},
{5,    1,    {5}},
{6,    2,    {2,    4}},
{7,    1,    {7}},
{8,    1,    {8}},
{9,    2,    {1,    8}},
{10,    1,    {10}},
{11,    1,    {11}},
{12,    1,    {12}},
{13,    1,    {13}},
{14,    1,    {14}},
{15,    1,    {15}},
{16,    1,    {16}},
{17,    1,    {17}},
{18,    2,    {2,    16}},
{19,    1,    {19}},
{20,    2,    {4,    16}},
{21,    1,    {21}},
{22,    3,    {2,    4,    16}},
{23,    1,    {23}},
{24,    2,    {16,    8}},
{25,    2,    {17,    8}},
{26,    2,    {10,    16}},
{27,    1,    {27}},
{28,    2,    {12,    16}},
{29,    1,    {29}},
{30,    2,    {14,    16}},
{31,    1,    {31}},
{32,    1,    {32}},
{33,    2,    {1,    32}},
{34,    1,    {34}},
{35,    1,    {35}},
{36,    2,    {4,    32}},
{37,    2,    {5,    32}},
{38,    2,    {34,    4}},
{39,    1,    {39}},
{40,    2,    {8,    32}},
{41,    3,    {1,    8,    32}},
{42,    1,    {42}},
{43,    1,    {43}},
{44,    2,    {12,    32}},
{45,    2,    {13,    32}},
{46,    1,    {46}},
{47,    1,    {47}},
{48,    1,    {48}},
{49,    1,    {49}},
{50,    1,    {50}},
{51,    1,    {51}},
{52,    2,    {48,    4}},
{53,    1,    {53}},
{54,    2,    {50,    4}},
{55,    1,    {55}},
{56,    2,    {48,    8}},
{57,    2,    {49,    8}},
{58,    1,    {58}},
{59,    1,    {59}},
{60,    2,    {12,    48}},
{61,    1,    {61}},
{62,    1,    {62}},
{63,    1,    {63}},
{64,    1,    {64}},
{65,    2,    {1,    64}},
{66,    2,    {2,    64}},
{67,    2,    {3,    64}},
{68,    1,    {68}},
{69,    1,    {69}},
{70,    2,    {68,    2}},
{71,    1,    {71}},
{72,    2,    {8,    64}},
{73,    3,    {1,    8,    64}},
{74,    2,    {10,    64}},
{75,    2,    {11,    64}},
{76,    1,    {76}},
{77,    1,    {77}},
{78,    1,    {78}},
{79,    1,    {79}},
{80,    1,    {80}},
{81,    1,    {81}},
{82,    2,    {80,    2}},
{83,    1,    {83}},
{84,    1,    {84}},
{85,    1,    {85}},
{86,    2,    {84,    2}},
{87,    1,    {87}},
{88,    2,    {80,    8}},
{89,    2,    {81,    8}},
{90,    2,    {10,    80}},
{91,    1,    {91}},
{92,    1,    {92}},
{93,    1,    {93}},
{94,    1,    {94}},
{95,    1,    {95}},
{96,    2,    {32,    64}},
{97,    3,    {1,    32,    64}},
{98,    2,    {34,    64}},
{99,    2,    {35,    64}},
{100,    2,    {68,    32}},
{101,    2,    {69,    32}},
{102,    2,    {34,    68}},
{103,    1,    {103}},
{104,    3,    {8,    32,    64}},
{105,    4,    {1,    8,    32,    64}},
{106,    2,    {42,    64}},
{107,    2,    {43,    64}},
{108,    2,    {76,    32}},
{109,    2,    {77,    32}},
{110,    1,    {110}},
{111,    1,    {111}},
{112,    1,    {112}},
{113,    1,    {113}},
{114,    1,    {114}},
{115,    1,    {115}},
{116,    1,    {116}},
{117,    1,    {117}},
{118,    1,    {118}},
{119,    1,    {119}},
{120,    2,    {112,    8}},
{121,    2,    {113,    8}},
{122,    1,    {122}},
{123,    1,    {123}},
{124,    1,    {124}},
{125,    1,    {125}},
{126,    2,    {127,    254}},
{127,    1,    {127}},
{128,    1,    {128}},
{129,    2,    {1,    128}},
{130,    2,    {2,    128}},
{131,    2,    {3,    128}},
{132,    2,    {4,    128}},
{133,    2,    {5,    128}},
{134,    3,    {2,    4,    128}},
{135,    2,    {7,    128}},
{136,    1,    {136}},
{137,    2,    {136,    1}},
{138,    1,    {138}},
{139,    1,    {139}},
{140,    1,    {140}},
{141,    1,    {141}},
{142,    1,    {142}},
{143,    1,    {143}},
{144,    2,    {16,    128}},
{145,    2,    {17,    128}},
{146,    3,    {2,    16,    128}},
{147,    2,    {19,    128}},
{148,    3,    {4,    16,    128}},
{149,    2,    {21,    128}},
{150,    4,    {2,    4,    16,    128}},
{151,    2,    {23,    128}},
{152,    2,    {136,    16}},
{153,    2,    {17,    136}},
{154,    2,    {138,    16}},
{155,    1,    {155}},
{156,    2,    {140,    16}},
{157,    1,    {157}},
{158,    2,    {142,    16}},
{159,    1,    {159}},
{160,    1,    {160}},
{161,    2,    {160,    1}},
{162,    1,    {162}},
{163,    1,    {163}},
{164,    2,    {160,    4}},
{165,    2,    {5,    160}},
{166,    2,    {162,    4}},
{167,    1,    {167}},
{168,    1,    {168}},
{169,    2,    {168,    1}},
{170,    1,    {170}},
{171,    1,    {171}},
{172,    1,    {172}},
{173,    1,    {173}},
{174,    1,    {174}},
{175,    1,    {175}},
{176,    1,    {176}},
{177,    1,    {177}},
{178,    1,    {178}},
{179,    1,    {179}},
{180,    2,    {176,    4}},
{181,    1,    {181}},
{182,    2,    {178,    4}},
{183,    1,    {183}},
{184,    1,    {184}},
{185,    1,    {185}},
{186,    1,    {186}},
{187,    1,    {187}},
{188,    1,    {188}},
{189,    2,    {253,    191}},
{190,    1,    {190}},
{191,    1,    {191}},
{192,    1,    {192}},
{193,    2,    {192,    1}},
{194,    2,    {192,    2}},
{195,    2,    {3,    192}},
{196,    1,    {196}},
{197,    1,    {197}},
{198,    2,    {196,    2}},
{199,    1,    {199}},
{200,    1,    {200}},
{201,    2,    {200,    1}},
{202,    1,    {202}},
{203,    1,    {203}},
{204,    1,    {204}},
{205,    1,    {205}},
{206,    1,    {206}},
{207,    1,    {207}},
{208,    1,    {208}},
{209,    1,    {209}},
{210,    2,    {208,    2}},
{211,    1,    {211}},
{212,    1,    {212}},
{213,    1,    {213}},
{214,    2,    {212,    2}},
{215,    1,    {215}},
{216,    1,    {216}},
{217,    1,    {217}},
{218,    1,    {218}},
{219,    2,    {251,    223}},
{220,    1,    {220}},
{221,    1,    {221}},
{222,    1,    {222}},
{223,    1,    {223}},
{224,    1,    {224}},
{225,    2,    {224,    1}},
{226,    1,    {226}},
{227,    1,    {227}},
{228,    1,    {228}},
{229,    1,    {229}},
{230,    1,    {230}},
{231,    2,    {239,    247}},
{232,    1,    {232}},
{233,    2,    {232,    1}},
{234,    1,    {234}},
{235,    1,    {235}},
{236,    1,    {236}},
{237,    1,    {237}},
{238,    1,    {238}},
{239,    1,    {239}},
{240,    1,    {240}},
{241,    1,    {241}},
{242,    1,    {242}},
{243,    1,    {243}},
{244,    1,    {244}},
{245,    1,    {245}},
{246,    1,    {246}},
{247,    1,    {247}},
{248,    1,    {248}},
{249,    1,    {249}},
{250,    1,    {250}},
{251,    1,    {251}},
{252,    1,    {252}},
{253,    1,    {253}},
{254,    1,    {254}},
{255,    1,    {0}}};


// Subtracting 1 from each direction translates Mathematica indices to
// C++ indices

const TNetExtractor::t2entry pt2[256] = {
{0,    1,    {-1},    {-1}},
{1,    3,    {3-1, 5-1, 1-1},    {0, 0, 0}},
{2,    3,    {5-1, 3-1, 2-1},    {1, 1, 1}},
{3,    4,    {3-1, 2-1, 5-1, 1-1},    {0, 1, 1, 0}},
{4,    3,    {5-1, 4-1, 1-1},    {2, 2, 2}},
{5,    4,    {3-1, 5-1, 4-1, 1-1},    {0, 0, 2, 2}},
{6,    1,    {-1},    {-1}},
{7,    5,    {3-1, 2-1, 5-1, 4-1, 1-1},    {0, 1, 1, 2, 2}},
{8,    3,    {4-1, 5-1, 2-1},    {3, 3, 3}},
{9,    1,    {-1},    {-1}},
{10,    4,    {4-1, 5-1, 3-1, 2-1},    {3, 3, 1, 1}},
{11,    5,    {3-1, 2-1, 4-1, 5-1, 1-1},    {0, 1, 3, 3, 0}},
{12,    4,    {5-1, 2-1, 4-1, 1-1},    {2, 3, 3, 2}},
{13,    5,    {3-1, 5-1, 2-1, 4-1, 1-1},    {0, 0, 3, 3, 2}},
{14,    5,    {5-1, 3-1, 2-1, 4-1, 1-1},    {2, 1, 1, 3, 2}},
{15,    4,    {3-1, 2-1, 4-1, 1-1},    {0, 1, 3, 2}},
{16,    3,    {6-1, 3-1, 1-1},    {4, 4, 4}},
{17,    4,    {6-1, 3-1, 5-1, 1-1},    {4, 4, 0, 0}},
{18,    1,    {-1},    {-1}},
{19,    5,    {6-1, 3-1, 2-1, 5-1, 1-1},    {4, 4, 1, 1, 0}},
{20,    1,    {-1},    {-1}},
{21,    5,    {6-1, 3-1, 5-1, 4-1, 1-1},    {4, 4, 0, 2, 2}},
{22,    1,    {-1},    {-1}},
{23,    6,    {6-1, 3-1, 2-1, 5-1, 4-1, 1-1},    {4, 4, 1, 1, 2, 2}},
{24,    1,    {-1},    {-1}},
{25,    1,    {-1},    {-1}},
{26,    1,    {-1},    {-1}},
{27,    6,    {6-1, 3-1, 2-1, 4-1, 5-1, 1-1},    {4, 4, 1, 3, 3, 0}},
{28,    1,    {-1},    {-1}},
{29,    6,    {6-1, 3-1, 5-1, 2-1, 4-1, 1-1},    {4, 4, 0, 3, 3, 2}},
{30,    1,    {-1},    {-1}},
{31,    5,    {6-1, 3-1, 2-1, 4-1, 1-1},    {4, 4, 1, 3, 2}},
{32,    3,    {3-1, 6-1, 2-1},    {5, 5, 5}},
{33,    1,    {-1},    {-1}},
{34,    4,    {5-1, 3-1, 6-1, 2-1},    {1, 1, 5, 5}},
{35,    5,    {3-1, 6-1, 2-1, 5-1, 1-1},    {0, 5, 5, 1, 0}},
{36,    1,    {-1},    {-1}},
{37,    1,    {-1},    {-1}},
{38,    1,    {-1},    {-1}},
{39,    6,    {3-1, 6-1, 2-1, 5-1, 4-1, 1-1},    {0, 5, 5, 1, 2, 2}},
{40,    1,    {-1},    {-1}},
{41,    1,    {-1},    {-1}},
{42,    5,    {4-1, 5-1, 3-1, 6-1, 2-1},    {3, 3, 1, 5, 5}},
{43,    6,    {3-1, 6-1, 2-1, 4-1, 5-1, 1-1},    {0, 5, 5, 3, 3, 0}},
{44,    1,    {-1},    {-1}},
{45,    1,    {-1},    {-1}},
{46,    6,    {5-1, 3-1, 6-1, 2-1, 4-1, 1-1},    {2, 1, 5, 5, 3, 2}},
{47,    5,    {3-1, 6-1, 2-1, 4-1, 1-1},    {0, 5, 5, 3, 2}},
{48,    4,    {6-1, 2-1, 3-1, 1-1},    {4, 5, 5, 4}},
{49,    5,    {6-1, 2-1, 3-1, 5-1, 1-1},    {4, 5, 5, 0, 0}},
{50,    5,    {6-1, 2-1, 5-1, 3-1, 1-1},    {4, 5, 1, 1, 4}},
{51,    4,    {6-1, 2-1, 5-1, 1-1},    {4, 5, 1, 0}},
{52,    1,    {-1},    {-1}},
{53,    6,    {6-1, 2-1, 3-1, 5-1, 4-1, 1-1},    {4, 5, 5, 0, 2, 2}},
{54,    1,    {-1},    {-1}},
{55,    5,    {6-1, 2-1, 5-1, 4-1, 1-1},    {4, 5, 1, 2, 2}},
{56,    1,    {-1},    {-1}},
{57,    1,    {-1},    {-1}},
{58,    6,    {6-1, 2-1, 4-1, 5-1, 3-1, 1-1},    {4, 5, 3, 3, 1, 4}},
{59,    5,    {6-1, 2-1, 4-1, 5-1, 1-1},    {4, 5, 3, 3, 0}},
{60,    1,    {-1},    {-1}},
{61,    7,    {5-1, 2-1, 4-1, 1-1, 6-1, 2-1, 3-1},    {0, 3, 3, 2, 4, 5, 5}},
{62,    7,    {5-1, 1-1, 4-1, 2-1, 6-1, 1-1, 3-1},    {1, 2, 2, 3, 5, 4, 4}},
{63,    4,    {6-1, 2-1, 4-1, 1-1},    {4, 5, 3, 2}},
{64,    3,    {4-1, 6-1, 1-1},    {6, 6, 6}},
{65,    1,    {-1},    {-1}},
{66,    1,    {-1},    {-1}},
{67,    1,    {-1},    {-1}},
{68,    4,    {5-1, 4-1, 6-1, 1-1},    {2, 2, 6, 6}},
{69,    5,    {3-1, 5-1, 4-1, 6-1, 1-1},    {0, 0, 2, 6, 6}},
{70,    1,    {-1},    {-1}},
{71,    6,    {3-1, 2-1, 5-1, 4-1, 6-1, 1-1},    {0, 1, 1, 2, 6, 6}},
{72,    1,    {-1},    {-1}},
{73,    1,    {-1},    {-1}},
{74,    1,    {-1},    {-1}},
{75,    1,    {-1},    {-1}},
{76,    5,    {5-1, 2-1, 4-1, 6-1, 1-1},    {2, 3, 3, 6, 6}},
{77,    6,    {3-1, 5-1, 2-1, 4-1, 6-1, 1-1},    {0, 0, 3, 3, 6, 6}},
{78,    6,    {5-1, 3-1, 2-1, 4-1, 6-1, 1-1},    {2, 1, 1, 3, 6, 6}},
{79,    5,    {3-1, 2-1, 4-1, 6-1, 1-1},    {0, 1, 3, 6, 6}},
{80,    4,    {4-1, 6-1, 3-1, 1-1},    {6, 6, 4, 4}},
{81,    5,    {4-1, 6-1, 3-1, 5-1, 1-1},    {6, 6, 4, 0, 0}},
{82,    1,    {-1},    {-1}},
{83,    6,    {4-1, 6-1, 3-1, 2-1, 5-1, 1-1},    {6, 6, 4, 1, 1, 0}},
{84,    5,    {5-1, 4-1, 6-1, 3-1, 1-1},    {2, 2, 6, 4, 4}},
{85,    4,    {5-1, 4-1, 6-1, 3-1},    {0, 2, 6, 4}},
{86,    1,    {-1},    {-1}},
{87,    5,    {5-1, 4-1, 6-1, 3-1, 2-1},    {1, 2, 6, 4, 1}},
{88,    1,    {-1},    {-1}},
{89,    1,    {-1},    {-1}},
{90,    1,    {-1},    {-1}},
{91,    7,    {5-1, 4-1, 2-1, 3-1, 6-1, 4-1, 1-1},    {0, 3, 3, 1, 4, 6, 6}},
{92,    6,    {5-1, 2-1, 4-1, 6-1, 3-1, 1-1},    {2, 3, 3, 6, 4, 4}},
{93,    5,    {4-1, 6-1, 3-1, 5-1, 2-1},    {3, 6, 4, 0, 3}},
{94,    7,    {5-1, 3-1, 2-1, 4-1, 6-1, 3-1, 1-1},    {2, 1, 1, 3, 6, 4, 4}},
{95,    4,    {4-1, 6-1, 3-1, 2-1},    {3, 6, 4, 1}},
{96,    1,    {-1},    {-1}},
{97,    1,    {-1},    {-1}},
{98,    1,    {-1},    {-1}},
{99,    1,    {-1},    {-1}},
{100,    1,    {-1},    {-1}},
{101,    1,    {-1},    {-1}},
{102,    1,    {-1},    {-1}},
{103,    7,    {3-1, 6-1, 2-1, 5-1, 4-1, 6-1, 1-1},    {0, 5, 5, 1, 2, 6, 6}},
{104,    1,    {-1},    {-1}},
{105,    1,    {-1},    {-1}},
{106,    1,    {-1},    {-1}},
{107,    1,    {-1},    {-1}},
{108,    1,    {-1},    {-1}},
{109,    1,    {-1},    {-1}},
{110,    7,    {2-1, 6-1, 3-1, 5-1, 1-1, 6-1, 4-1},    {3, 5, 5, 1, 2, 6, 6}},
{111,    6,    {3-1, 1-1, 6-1, 4-1, 2-1, 6-1},    {5, 0, 6, 6, 3, 5}},
{112,    5,    {4-1, 6-1, 2-1, 3-1, 1-1},    {6, 6, 5, 5, 4}},
{113,    6,    {4-1, 6-1, 2-1, 3-1, 5-1, 1-1},    {6, 6, 5, 5, 0, 0}},
{114,    6,    {4-1, 6-1, 2-1, 5-1, 3-1, 1-1},    {6, 6, 5, 1, 1, 4}},
{115,    5,    {4-1, 6-1, 2-1, 5-1, 1-1},    {6, 6, 5, 1, 0}},
{116,    6,    {5-1, 4-1, 6-1, 2-1, 3-1, 1-1},    {2, 2, 6, 5, 5, 4}},
{117,    5,    {3-1, 5-1, 4-1, 6-1, 2-1},    {5, 0, 2, 6, 5}},
{118,    7,    {3-1, 5-1, 2-1, 6-1, 4-1, 5-1, 1-1},    {4, 1, 1, 5, 6, 2, 2}},
{119,    4,    {5-1, 4-1, 6-1, 2-1},    {1, 2, 6, 5}},
{120,    1,    {-1},    {-1}},
{121,    1,    {-1},    {-1}},
{122,    7,    {2-1, 4-1, 5-1, 3-1, 1-1, 4-1, 6-1},    {5, 3, 3, 1, 4, 6, 6}},
{123,    6,    {5-1, 1-1, 4-1, 6-1, 2-1, 4-1},    {3, 0, 6, 6, 5, 3}},
{124,    7,    {4-1, 2-1, 5-1, 1-1, 3-1, 2-1, 6-1},    {6, 3, 3, 2, 4, 5, 5}},
{125,    6,    {5-1, 3-1, 2-1, 6-1, 4-1, 2-1},    {3, 0, 5, 5, 6, 3}},
{126,    1,    {-1},    {-1}},
{127,    3,    {4-1, 6-1, 2-1},    {3, 6, 5}},
{128,    3,    {6-1, 4-1, 2-1},    {7, 7, 7}},
{129,    1,    {-1},    {-1}},
{130,    1,    {-1},    {-1}},
{131,    1,    {-1},    {-1}},
{132,    1,    {-1},    {-1}},
{133,    1,    {-1},    {-1}},
{134,    1,    {-1},    {-1}},
{135,    1,    {-1},    {-1}},
{136,    4,    {6-1, 4-1, 5-1, 2-1},    {7, 7, 3, 3}},
{137,    1,    {-1},    {-1}},
{138,    5,    {6-1, 4-1, 5-1, 3-1, 2-1},    {7, 7, 3, 1, 1}},
{139,    6,    {3-1, 2-1, 6-1, 4-1, 5-1, 1-1},    {0, 1, 7, 7, 3, 0}},
{140,    5,    {5-1, 2-1, 6-1, 4-1, 1-1},    {2, 3, 7, 7, 2}},
{141,    6,    {3-1, 5-1, 2-1, 6-1, 4-1, 1-1},    {0, 0, 3, 7, 7, 2}},
{142,    6,    {5-1, 3-1, 2-1, 6-1, 4-1, 1-1},    {2, 1, 1, 7, 7, 2}},
{143,    5,    {3-1, 2-1, 6-1, 4-1, 1-1},    {0, 1, 7, 7, 2}},
{144,    1,    {-1},    {-1}},
{145,    1,    {-1},    {-1}},
{146,    1,    {-1},    {-1}},
{147,    1,    {-1},    {-1}},
{148,    1,    {-1},    {-1}},
{149,    1,    {-1},    {-1}},
{150,    1,    {-1},    {-1}},
{151,    1,    {-1},    {-1}},
{152,    1,    {-1},    {-1}},
{153,    1,    {-1},    {-1}},
{154,    1,    {-1},    {-1}},
{155,    7,    {3-1, 6-1, 1-1, 5-1, 4-1, 6-1, 2-1},    {1, 4, 4, 0, 3, 7, 7}},
{156,    1,    {-1},    {-1}},
{157,    7,    {1-1, 6-1, 3-1, 5-1, 2-1, 6-1, 4-1},    {2, 4, 4, 0, 3, 7, 7}},
{158,    1,    {-1},    {-1}},
{159,    6,    {3-1, 2-1, 6-1, 4-1, 1-1, 6-1},    {4, 1, 7, 7, 2, 4}},
{160,    4,    {3-1, 6-1, 4-1, 2-1},    {5, 5, 7, 7}},
{161,    1,    {-1},    {-1}},
{162,    5,    {5-1, 3-1, 6-1, 4-1, 2-1},    {1, 1, 5, 7, 7}},
{163,    6,    {3-1, 6-1, 4-1, 2-1, 5-1, 1-1},    {0, 5, 7, 7, 1, 0}},
{164,    1,    {-1},    {-1}},
{165,    1,    {-1},    {-1}},
{166,    1,    {-1},    {-1}},
{167,    7,    {5-1, 4-1, 1-1, 3-1, 6-1, 4-1, 2-1},    {1, 2, 2, 0, 5, 7, 7}},
{168,    5,    {3-1, 6-1, 4-1, 5-1, 2-1},    {5, 5, 7, 3, 3}},
{169,    1,    {-1},    {-1}},
{170,    4,    {6-1, 4-1, 5-1, 3-1},    {5, 7, 3, 1}},
{171,    5,    {3-1, 6-1, 4-1, 5-1, 1-1},    {0, 5, 7, 3, 0}},
{172,    6,    {5-1, 2-1, 3-1, 6-1, 4-1, 1-1},    {2, 3, 5, 5, 7, 2}},
{173,    7,    {5-1, 3-1, 1-1, 4-1, 6-1, 3-1, 2-1},    {3, 0, 0, 2, 7, 5, 5}},
{174,    5,    {5-1, 3-1, 6-1, 4-1, 1-1},    {2, 1, 5, 7, 2}},
{175,    4,    {3-1, 6-1, 4-1, 1-1},    {0, 5, 7, 2}},
{176,    5,    {6-1, 4-1, 2-1, 3-1, 1-1},    {4, 7, 7, 5, 4}},
{177,    6,    {6-1, 4-1, 2-1, 3-1, 5-1, 1-1},    {4, 7, 7, 5, 0, 0}},
{178,    6,    {6-1, 4-1, 2-1, 5-1, 3-1, 1-1},    {4, 7, 7, 1, 1, 4}},
{179,    5,    {6-1, 4-1, 2-1, 5-1, 1-1},    {4, 7, 7, 1, 0}},
{180,    1,    {-1},    {-1}},
{181,    7,    {1-1, 4-1, 5-1, 3-1, 2-1, 4-1, 6-1},    {4, 2, 2, 0, 5, 7, 7}},
{182,    1,    {-1},    {-1}},
{183,    6,    {5-1, 2-1, 4-1, 6-1, 1-1, 4-1},    {2, 1, 7, 7, 4, 2}},
{184,    6,    {6-1, 4-1, 5-1, 2-1, 3-1, 1-1},    {4, 7, 3, 3, 5, 4}},
{185,    7,    {3-1, 5-1, 1-1, 6-1, 4-1, 5-1, 2-1},    {5, 0, 0, 4, 7, 3, 3}},
{186,    5,    {6-1, 4-1, 5-1, 3-1, 1-1},    {4, 7, 3, 1, 4}},
{187,    4,    {6-1, 4-1, 5-1, 1-1},    {4, 7, 3, 0}},
{188,    7,    {4-1, 1-1, 5-1, 2-1, 3-1, 1-1, 6-1},    {7, 2, 2, 3, 5, 4, 4}},
{189,    1,    {-1},    {-1}},
{190,    6,    {5-1, 3-1, 1-1, 6-1, 4-1, 1-1},    {2, 1, 4, 4, 7, 2}},
{191,    3,    {6-1, 4-1, 1-1},    {4, 7, 2}},
{192,    4,    {4-1, 2-1, 6-1, 1-1},    {6, 7, 7, 6}},
{193,    1,    {-1},    {-1}},
{194,    1,    {-1},    {-1}},
{195,    1,    {-1},    {-1}},
{196,    5,    {5-1, 4-1, 2-1, 6-1, 1-1},    {2, 2, 7, 7, 6}},
{197,    6,    {3-1, 5-1, 4-1, 2-1, 6-1, 1-1},    {0, 0, 2, 7, 7, 6}},
{198,    1,    {-1},    {-1}},
{199,    7,    {5-1, 2-1, 3-1, 1-1, 6-1, 2-1, 4-1},    {2, 1, 1, 0, 6, 7, 7}},
{200,    5,    {4-1, 5-1, 2-1, 6-1, 1-1},    {6, 3, 3, 7, 6}},
{201,    1,    {-1},    {-1}},
{202,    6,    {4-1, 5-1, 3-1, 2-1, 6-1, 1-1},    {6, 3, 1, 1, 7, 6}},
{203,    7,    {5-1, 1-1, 3-1, 2-1, 6-1, 1-1, 4-1},    {3, 0, 0, 1, 7, 6, 6}},
{204,    4,    {5-1, 2-1, 6-1, 1-1},    {2, 3, 7, 6}},
{205,    5,    {3-1, 5-1, 2-1, 6-1, 1-1},    {0, 0, 3, 7, 6}},
{206,    5,    {5-1, 3-1, 2-1, 6-1, 1-1},    {2, 1, 1, 7, 6}},
{207,    4,    {3-1, 2-1, 6-1, 1-1},    {0, 1, 7, 6}},
{208,    5,    {4-1, 2-1, 6-1, 3-1, 1-1},    {6, 7, 7, 4, 4}},
{209,    6,    {4-1, 2-1, 6-1, 3-1, 5-1, 1-1},    {6, 7, 7, 4, 0, 0}},
{210,    1,    {-1},    {-1}},
{211,    7,    {3-1, 2-1, 5-1, 1-1, 4-1, 2-1, 6-1},    {4, 1, 1, 0, 6, 7, 7}},
{212,    6,    {5-1, 4-1, 2-1, 6-1, 3-1, 1-1},    {2, 2, 7, 7, 4, 4}},
{213,    5,    {6-1, 3-1, 5-1, 4-1, 2-1},    {7, 4, 0, 2, 7}},
{214,    1,    {-1},    {-1}},
{215,    6,    {5-1, 4-1, 2-1, 6-1, 3-1, 2-1},    {1, 2, 7, 7, 4, 1}},
{216,    6,    {4-1, 5-1, 2-1, 6-1, 3-1, 1-1},    {6, 3, 3, 7, 4, 4}},
{217,    7,    {1-1, 5-1, 3-1, 6-1, 2-1, 5-1, 4-1},    {6, 0, 0, 4, 7, 3, 3}},
{218,    7,    {2-1, 3-1, 5-1, 4-1, 1-1, 3-1, 6-1},    {7, 1, 1, 3, 6, 4, 4}},
{219,    1,    {-1},    {-1}},
{220,    5,    {5-1, 2-1, 6-1, 3-1, 1-1},    {2, 3, 7, 4, 4}},
{221,    4,    {6-1, 3-1, 5-1, 2-1},    {7, 4, 0, 3}},
{222,    6,    {5-1, 1-1, 3-1, 6-1, 2-1, 3-1},    {1, 2, 4, 4, 7, 1}},
{223,    3,    {6-1, 3-1, 2-1},    {7, 4, 1}},
{224,    5,    {4-1, 2-1, 3-1, 6-1, 1-1},    {6, 7, 5, 5, 6}},
{225,    1,    {-1},    {-1}},
{226,    6,    {4-1, 2-1, 5-1, 3-1, 6-1, 1-1},    {6, 7, 1, 1, 5, 6}},
{227,    7,    {3-1, 1-1, 5-1, 2-1, 4-1, 1-1, 6-1},    {5, 0, 0, 1, 7, 6, 6}},
{228,    6,    {5-1, 4-1, 2-1, 3-1, 6-1, 1-1},    {2, 2, 7, 5, 5, 6}},
{229,    7,    {1-1, 3-1, 5-1, 4-1, 2-1, 3-1, 6-1},    {6, 0, 0, 2, 7, 5, 5}},
{230,    7,    {2-1, 5-1, 3-1, 6-1, 1-1, 5-1, 4-1},    {7, 1, 1, 5, 6, 2, 2}},
{231,    1,    {-1},    {-1}},
{232,    6,    {4-1, 5-1, 2-1, 3-1, 6-1, 1-1},    {6, 3, 3, 5, 5, 6}},
{233,    1,    {-1},    {-1}},
{234,    5,    {4-1, 5-1, 3-1, 6-1, 1-1},    {6, 3, 1, 5, 6}},
{235,    6,    {5-1, 4-1, 1-1, 6-1, 3-1, 1-1},    {0, 3, 6, 6, 5, 0}},
{236,    5,    {5-1, 2-1, 3-1, 6-1, 1-1},    {2, 3, 5, 5, 6}},
{237,    6,    {5-1, 2-1, 3-1, 6-1, 1-1, 3-1},    {0, 3, 5, 5, 6, 0}},
{238,    4,    {5-1, 3-1, 6-1, 1-1},    {2, 1, 5, 6}},
{239,    3,    {3-1, 6-1, 1-1},    {0, 5, 6}},
{240,    4,    {4-1, 2-1, 3-1, 1-1},    {6, 7, 5, 4}},
{241,    5,    {4-1, 2-1, 3-1, 5-1, 1-1},    {6, 7, 5, 0, 0}},
{242,    5,    {4-1, 2-1, 5-1, 3-1, 1-1},    {6, 7, 1, 1, 4}},
{243,    4,    {4-1, 2-1, 5-1, 1-1},    {6, 7, 1, 0}},
{244,    5,    {5-1, 4-1, 2-1, 3-1, 1-1},    {2, 2, 7, 5, 4}},
{245,    4,    {3-1, 5-1, 4-1, 2-1},    {5, 0, 2, 7}},
{246,    6,    {3-1, 1-1, 5-1, 4-1, 2-1, 5-1},    {1, 4, 2, 2, 7, 1}},
{247,    3,    {5-1, 4-1, 2-1},    {1, 2, 7}},
{248,    5,    {4-1, 5-1, 2-1, 3-1, 1-1},    {6, 3, 3, 5, 4}},
{249,    6,    {3-1, 2-1, 5-1, 4-1, 1-1, 5-1},    {0, 5, 3, 3, 6, 0}},
{250,    4,    {4-1, 5-1, 3-1, 1-1},    {6, 3, 1, 4}},
{251,    3,    {4-1, 5-1, 1-1},    {6, 3, 0}},
{252,    4,    {5-1, 2-1, 3-1, 1-1},    {2, 3, 5, 4}},
{253,    3,    {3-1, 5-1, 2-1},    {5, 0, 3}},
{254,    3,    {5-1, 3-1, 1-1},    {2, 1, 4}},
{255,    1,    {-1},    {-1}}
};

TVertex::TVertex()
{
   wh_[0] = wh_[1] = wh_[2] = count_ = 0;
   for (int i = 0; i < 14; ++i)
      neighb_[i] = 0;
}
 
TVertex::TVertex(int wh[3], int count, int neighb[14])
{
   wh_[0] = wh[0]; wh_[1] = wh[1]; wh_[2] = wh[2];
   count_ = count;
   for (int i = 0; i < count; ++i)
      neighb_[i] = neighb[i];
}
 
 
int operator==(const TVertex& v1, const TVertex& v2)
{
   if (v2.count_ != v1.count_)
      return 0;
 
   int result = (v1.wh_[0] == v2.wh_[0] && v1.wh_[1] == v2.wh_[1] && v1.wh_[2] == v2.wh_[2]);
   for (int i = 0; i < v2.count_; ++i)
      result = result && (v1.neighb_[i] == v2.neighb_[i]);
 
   return result;
}
 
 
std::ostream& operator<<(std::ostream& os, const TVertex& v)
{
   os << "{{" << v.wh_[0] << ", " << v.wh_[1] << ", " << v.wh_[2] << "}, {";
   for (int i = 0; i < v.count_; ++i) {
      os << v.neighb_[i];
      if (i != v.count_-1)
         os << ", ";
   }
   os << "}}";
   return os;
}


void TVertexArray::init(const TVertex* ar, int sz)
{
    ia_ = new TVertex[size_ = sz];
    TVertex defaultVertex;

    for (int ix = 0; ix < size_; ++ix)
         ia_[ix] = (ar != 0) ? ar[ix] : defaultVertex;
}

TVertexArray& TVertexArray::operator=(const TVertexArray& iA)
{
    if (this == &iA) return *this;
    delete ia_; 
    init( iA.ia_, iA.size_ );
    return *this;
}

int TVertexArray::find(TVertex val) const
{ 
    for (int i=0; i<size_; ++i)
         if (val == ia_[i]) return i;
    return -1;
}

void TVertexArray::print(std::ostream& os) const
{
    for (int i = 0; i < size_; ++i) { 
       os << ia_[i];
       if (i != (size_-1) ) 
               os << ",\n";
    }
    os << "\n";
}


std::ostream& operator<< (std::ostream& os, const TVertexArray& ar) 
{
    ar.print(os);
    return os;
}
TVertexList::~TVertexList() {
   if (last_) {
      TVertexItem* ptr = last_->next_;
      last_->next_ = 0;
      while (ptr) {
         TVertexItem* tmp = ptr;
         ptr = ptr->next_;
         delete tmp;
      }
   }
}
 
TVertexItem* TVertexList::search(TVertex val) const
{
   TVertexItem* p = 0;
   forall_vertexlistitems(p, *this)
      if (p->val_ == val)
         break;
 
   return p;
}
 
int TVertexList::contains(TVertex val) const
{
   TVertexItem* p = 0;
   forall_vertexlistitems(p, *this)
      if (p->val_ == val)
         return 1;
 
   return 0;
}
  
int TVertexList::size() const
{
   int i = 0;
   TVertexItem* a;
   forall_vertexlistitems(a, *this)
      i++;
 
   return i;
}
 
void TVertexList::insert(TVertex val) {
   TVertexItem* a = new TVertexItem(val);
   if (last_)
      a->next_ = last_->next_;
   else
      last_ = a;
   last_->next_ = a;
}
 
void TVertexList::append(TVertex val)
{
   TVertexItem* a = new TVertexItem(val);
   if (last_) {
      a->next_ = last_->next_;
      last_ = last_->next_ = a;
   }
   else
      last_ = a->next_ = a;
}
                                                                                                                                                                   
TVertex TVertexList::pop()
{
 
   TVertexItem* f = last_->next_;
   if (f == last_)
                last_ = 0;
   else
      last_->next_ = f->next_;
 
   static TVertexItem * last = NULL;
   if (last) delete last;
 
   last = f;
 
   return f->val_;
}
  
void TVertexList::remove(TVertexItem* it)
{
   TVertexItem* before = it;
 
   while (before->next_ != it) before=before->next_;
   before->next_ = it->next_;
   if (last_ == it) last_ = before;
   if (before == it) last_ = 0;
   delete it;
}
 
void TVertexList::insert_after(TVertex val, TVertexItem* it)
{
   TVertexItem* a = new TVertexItem(val);
   a->next_ = it->next_;
   it->next_ = a;
   if (it == last_) last_ = a;
}
  
void TVertexList::print(std::ostream& os) const
{
   int first = 1;
   if(!empty()) {
      for(TVertexItem* ptr = last_->next_;; ptr = ptr->next_) {
         if (first) first = 0;
         else      os << ", \n";
         os << ptr->val_;
         if (ptr == last_)
            break;
      }
   }
   os << std::endl;
}
 
  
std::ostream& operator<< (std::ostream& os, const TVertexList& li)
{
   li.print(os);
   return os;
}


TSurfaceNet::TSurfaceNet(TVoxelVolume& vol, int thresh)
{
   // build a surface net using a TNetExtractor object
   thresh_ = (unsigned char) thresh;
   va_ = 0;
   this->vol2net(vol);
}

void TSurfaceNet::read(std::istream& is)
{
    char ch;
    int wh[3];
    int count;
    int neighb[14];
    TVertexList vl;
    
    is >> ch;
    for (;;) {
        is >> ch;
        if (ch == '}')
            break;
            
        is >> ch; is >> wh[0]; 
        is >> ch; is >> wh[1];
        is >> ch; is >> wh[2];
        is >> ch; is >> ch; is >> ch;
        for (count = 0; ; count++) {
            is >> neighb[count];
            is >> ch;
            if (ch == '}') {
                count++;
                break;
            }
        }
        TVertex v(wh,count,neighb);
        vl.append(v);
        is >> ch; // '}'
        is >> ch; // ','
        if (ch == '}')
            break;
    }
    int i = 0;
    int L = vl.length();
    va_ = new TVertexArray(L);
    while (! vl.empty() ) {
       TVertex v = vl.pop();
       (*va_)[i] = v;
       ++i;
    }
}

void TSurfaceNet::print(std::ostream& os) const
{
    os << "{" << std::endl;
    (*va_).print(os);
    os << "}" << std::endl;
}
    
int TSurfaceNet::GetIndex(const TPoint3D& pt) const
{
   for (int i=0; i<va_->size(); ++i)
      if ((*va_)[i].GetCoords3D() == pt)
     return i;

   return -1;
}

int TSurfaceNet::nface() const
{
   // count faces
   int nfaces = 0;
   for (int i=0; i<va_->size(); ++i) {
      TVertex v = (*va_)[i];
      for (int j=0; j+1 <v.count_; j+=2) {
     int second = (j+2)%v.count_;
     if (v.neighb_[j     ] > i &&
         v.neighb_[j+1   ] > i &&
         v.neighb_[second] > i) {
           nfaces++;
     }
      }
   }
   return (nfaces);
}
    

void TSurfaceNet::vol2net(TVoxelVolume& vol)
{
   vol.SetBoundary(0);
   vol.Binarize(thresh_);

   TNetExtractor ne(&vol);
   TVertexList* vl;
   vl = ne.extractnet();
   int i = 0;
   int L = vl->length();
   va_ = new TVertexArray(L);
   while (! vl->empty() ) {
      TVertex v = vl->pop();
      (*va_)[i] = v;
      ++i; 
   }
   delete vl;
}
    
std::ostream& operator<< (std::ostream& os, const TSurfaceNet& sn)
{
    sn.print(os);
    return os;
}

int TNetExtractor::direct_translate(int dir, int ne)
{
   int trne = tr_direct[dir][ne];
   return trne;
}

#define DIR(D1,D2) (( (dir1 == D1) && (dir2 == D2)) || ((dir1 == D2) && (dir2 == D1)) )
int TNetExtractor::diag_translate(int dir1, int dir2, int ne)
{
   // ugly (we could do better)
    int trne = 0;
    
    if DIR(S,E) {
        switch(ne) {
            case 1: trne = 2; break;
            case 5: trne = 6; break;
            case 3: trne = -1; break;
        }
    }
    else if DIR(E,N) {
        switch(ne) {
            case 3: trne = 0; break;
            case 7: trne = 4; break;
        }
    }
    else if DIR(N,W) {
        switch(ne) {
            case 6: trne = 5; break;
            case 2: trne = 1; break;
        }
    }
    else if DIR(W,S) {
        switch(ne) {
            case 4: trne = 7; break;
            case 0: trne = 3; break;
        }
    }
    else if DIR(T,S) {
        switch(ne) {
            case 4: trne = 2; break;
            case 5: trne = 3; break;
        }
    }
    else if DIR(S,B) {
        switch(ne) {
            case 0: trne = 6; break;
            case 1: trne = 7; break;
        }
    }
    else if DIR(B,N) {
        switch(ne) {
            case 2: trne = 4; break;
            case 3: trne = 5; break;
        }
    }
    else if DIR(N,T) {
        switch(ne) {
            case 6: trne = 0; break;
            case 7: trne = 1; break;
        }
    }
    else if DIR(E,T) {
        switch(ne) {
            case 5: trne = 0; break;
            case 7: trne = 2; break;
        }
    }
    else if DIR(T,W) {
        switch(ne) {
            case 4: trne = 1; break;
            case 6: trne = 3; break;
        }
    }
    else if DIR(W,B) {
        switch(ne) {
            case 0: trne = 5; break;
            case 2: trne = 7; break;
        }
    }
    else if DIR(B,E) {
        switch(ne) {
            case 1: trne = 4; break;
            case 3: trne = 6; break;
        }
    }
    return trne;
}

void TNetExtractor::encode(int nx, int ny, int nz, int& number, 
               unsigned char* nbc, numentry* num, int z)
{
   int y, x, i, j;
   unsigned char code;
    
   for(y=0;y<ny;y++) {
      for (x=0;x<nx;x++) {
     code = 0;
     for (i=0;i<8;i++) 
        code |= (*vol_)(x+i%2, y+i/2%2, z+i/4) & 1<<i;
     nbc[x+nx*y]=code;
     numentry* num_act = &num[x+nx*y];

     if (code==126) {
        num_act->nums[3] = num_act->nums[5] = num_act->nums[6] = number;
        number++;
        num_act->nums[1] = num_act->nums[2] = num_act->nums[4] = number;
        number++;
     }
          
     else if (code==189) {
        num_act->nums[0] = num_act->nums[3] = num_act->nums[5] = number;
        number++;
        num_act->nums[2] = num_act->nums[4] = num_act->nums[7] = number;
        number++;
     }

     else if (code==219) {
        num_act->nums[0] = num_act->nums[3] = num_act->nums[6] = number;
        number++;
        num_act->nums[1] = num_act->nums[4] = num_act->nums[7] = number;
        number++;
     }
         
     else if (code==231) {
        num_act->nums[0] = num_act->nums[5] = num_act->nums[6] = number;
        number++;
        num_act->nums[1] = num_act->nums[2] = num_act->nums[7] = number;
        number++;
     }
    
     else {
        for(i=0;i<pt1[code].count;i++) {
           unsigned char nc_act = pt1[code].nbcs[i];
           if (nc_act) {
          for (j=0;j<8;j++) {
             if (nc_act & (1 << j))
            num_act->nums[j] = number;
          }
          number++;
           }
        }
     }
      }
   }
}

TVertexList* TNetExtractor::extractnet()
{
   int i,j, k, x, y, z, xy;
   int number = 0;
   int nx = vol_->Nx();
   int ny = vol_->Ny();
   int nz = vol_->Nz();

   int z_tab[]  = { 0,0,0,0,-1,1 };
   int xy_tab[] = { -1, 1, -nx, nx, 0, 0 };    
    
   numentry* num[3];
   num[0] = new numentry[nx*ny*3];
   num[1] = num[0] + nx*ny;
   num[2] = num[1] + nx*ny;
   numentry* num_remember = num[0];
    
   // dbg
   for (i=0;i<nx*ny*3;i++)
      for (j=0;j<8;j++)
     num[0][i].nums[j] = -1;

   unsigned char *nbc_this, *nbc_next, *nbc_remember;
   nbc_this = new unsigned char[nx*ny*2];
   nbc_remember =  nbc_this;
   nbc_next = nbc_this + nx*ny;

   encode(nx, ny, nz, number, nbc_next, num[2], 0);

   TVertexList* vl = new TVertexList; // collect vertices in this list

   for (z=0; z<nz-1; z++) {

      numentry* help_i=num[0]; num[0]=num[1]; num[1]=num[2]; num[2]=help_i;
      unsigned char* help_u=nbc_this; nbc_this=nbc_next; nbc_next=help_u;
        
      if (z<nz-2)
     encode(nx,ny,nz,number,nbc_next,num[2],z+1);
        
      for (y=0;y<ny-1;y++) {
     for (x=0;x<nx-1;x++) {

        // nc is the nbc as encounterd in the input data volume
        unsigned char nc;
        if (nc = nbc_this[xy = x+nx*y]) {
                    
           for(i=0;i<pt1[nc].count;i++) {

          // according  to table1, we split nc into pieces to get an "actual" nbc
          unsigned char nc_act = pt1[nc].nbcs[i];
          if (nc_act) {
             int wh_act[3];
             int count_act = 0;
             int neighb_act[14];
             wh_act[0] = x+1; wh_act[1] = y+1; wh_act[2] = z+1;
            
             int count2 = pt2[nc_act].count;

             // the values where to look for the neighbor's numbers in the num array are precomputed
             // and stored in table pt2
             for(k=0;k<count2;k++) {

            int dir1 = pt2[nc_act].dir[k];
            int dir2 = pt2[nc_act].dir[(k+1)%count2];
            int ne1  = pt2[nc_act].ne[k];
            int ne2  = pt2[nc_act].ne[(k+1)%count2];

            int t_ne1 = direct_translate(dir1,ne1);
            int num_act = num[1+z_tab[dir1]][xy+xy_tab[dir1]].nums[t_ne1];
            neighb_act[count_act++] = num_act;

            int t_ne2 = diag_translate(dir1,dir2,ne2);
            numentry dbg = num[1+z_tab[dir1]+z_tab[dir2]][xy+xy_tab[dir1]+xy_tab[dir2]];
            num_act = num[1+z_tab[dir1]+z_tab[dir2]]
               [xy+xy_tab[dir1]+xy_tab[dir2]].nums[t_ne2];
            neighb_act[count_act++] = num_act;
             }

             // save vertex
             TVertex v(wh_act, count_act, neighb_act);
             vl->append(v);

          }// if(nc_act)
           }
        }
     }
      }
   }
   
   delete [] nbc_remember;
   delete [] num_remember;;

   return vl;
}
